package org.cytoscape.myapp.cytoscape_app_v1.internal.helpers;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.cytoscape.model.CyColumn;
import org.cytoscape.model.CyEdge;
import org.cytoscape.model.CyEdge.Type;
import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNode;
import org.cytoscape.model.CyTable;
import org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.domain.TrustedRelationship;
import org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.domain.User;
import org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.domain.UserPositionMapping;
import org.cytoscape.view.model.CyNetworkView;



/**
 * Esta clase se agregaran metodos estaticos para acceder a informacion de la red
 * 
 */
 
public class ModelUtils {
	
	
	public static CyColumn getCyColumnNetwork(CyNetwork network, String nameColumn){
		
		CyTable table = network.getDefaultNodeTable();
		
		return table.getColumn(nameColumn);
		
	}
	
	public static HashMap<CyNode,List<Object>> getAllNodesWhitAttributes(CyNetwork network, String nameColumn){
		
		CyColumn columna = getCyColumnNetwork(network, nameColumn);
		
		List<CyNode> nodes = network.getNodeList();

		HashMap<CyNode,List<Object>> nodeAttributes = new HashMap<CyNode, List<Object>>(); 
		
		try{
				
				if (columna.getListElementType().equals(String.class)){
					for(CyNode node:nodes){				
						List<String> lista = network.getDefaultNodeTable().getRow(node.getSUID()).getList(nameColumn, String.class);
						List<Object> lisNodo = new Vector<Object>();
						for (String elem:lista)
							lisNodo.add(elem);
						nodeAttributes.put(node, lisNodo);					
					}
				}
				if (columna.getListElementType().equals(Integer.class)){
					for(CyNode node:nodes){				
						List<Integer> lista = network.getDefaultNodeTable().getRow(node.getSUID()).getList(nameColumn, Integer.class);
						List<Object> lisNodo = new Vector<Object>();
						for (Integer elem:lista)
							lisNodo.add(elem);
						nodeAttributes.put(node, lisNodo);					
					}
				}
			}
			catch (Exception e){
				System.out.println("No existe columna");
				e.printStackTrace();
			}
		return nodeAttributes;
	}
	
	public static Set<Object> getValuesCyColumnNetwork(CyNetwork network, String nameColumn){
		
		CyColumn columna = getCyColumnNetwork(network, nameColumn);
		
		Set<Object> values = new  HashSet<Object>();
		try {
			values.addAll(columna.getValues(columna.getType()));
		}
		catch (Exception e){
			e.printStackTrace();
			System.out.println("No Existe Columna");
		}
		return values;
	}

	public static HashMap<CyNode,List<Object>> getAllNodesWhitAttributesSimple(CyNetwork network, String nameColumn) {
		
		CyColumn columna = getCyColumnNetwork(network, nameColumn);
		
		List<CyNode> nodes = network.getNodeList();

		HashMap<CyNode,List<Object>> nodeAttributes = new HashMap<CyNode, List<Object>>(); 
		
		try{
			if (columna.getType().equals(String.class)){
				for(CyNode node:nodes){				
					Object lista = network.getDefaultNodeTable().getRow(node.getSUID()).get(nameColumn, String.class);
					List<Object> lisNodo = new Vector<Object>();
					lisNodo.add(lista);
					nodeAttributes.put(node, lisNodo);				
					}
				}
			}
			catch (Exception e){
				System.out.println("No existe columna");
				e.printStackTrace();
			}
		return nodeAttributes;
	}
	
	public static void updateTableNode(String columnName, double[] sc, 
						UserPositionMapping userPositionMapping, CyNetwork cyNetwork){
		
		if (cyNetwork.getDefaultNodeTable().getColumn(columnName) == null)
			cyNetwork.getDefaultNodeTable().createColumn(columnName, Double.class, false);
		
		
		List<CyNode> nodes = cyNetwork.getNodeList();
		
		for(CyNode node:nodes){
			String userId = cyNetwork.getDefaultNodeTable().getRow(node.getSUID()).get("shared name", String.class); 
			System.out.println(userId);
			cyNetwork.getDefaultNodeTable().getRow(node.getSUID()).set(columnName, sc[userPositionMapping.getPositionByUserId(userId)]);
		}
		
	}

	public static void updateTableEdge(String columnName, double[][] sm, 
						UserPositionMapping userPositionMapping, CyNetwork cyNetwork){

		if (cyNetwork.getDefaultEdgeTable().getColumn(columnName) == null)
			cyNetwork.getDefaultEdgeTable().createColumn(columnName, Double.class, false);
		
//		List<CyEdge> edges = cyNetwork.getEdgeList();
//		
//		for(CyEdge edge:edges){
//			String[] usersIds = cyNetwork.getDefaultEdgeTable().getRow(edge.getSUID()).get("shared name", String.class).split(" ");
//			
//			cyNetwork.getDefaultEdgeTable().getRow(edge.getSUID()).set(columnName, 
//			sm[userPositionMapping.getPositionByUserId(usersIds[0])][userPositionMapping.getPositionByUserId(usersIds[2])]);
//		}
		
		for (int i = 0; i < sm.length; i++) {
			for (int j = i; j < sm.length; j++) {
				if (i != j){
					String userId1 = userPositionMapping.getUserIdByPosition(i);
					String userId2 = userPositionMapping.getUserIdByPosition(j);
					CyNode user1 = cyNetwork.getNode(userPositionMapping.getUsers().get(userId1).getSuid());
					CyNode user2 = cyNetwork.getNode(userPositionMapping.getUsers().get(userId2).getSuid());
					List<CyEdge> edges =null;
					if (cyNetwork.containsEdge(user1, user2)){
						edges = cyNetwork.getConnectingEdgeList(user1, user2, Type.ANY);
					}
					if (cyNetwork.containsEdge(user2, user1)){
						edges = cyNetwork.getConnectingEdgeList(user2, user1, Type.ANY);
					}
					if ((edges !=null) && (!edges.isEmpty())){
						//if(cyNetwork.getDefaultEdgeTable().getRow(edges.get(0).getSUID()).get(columnName, Double.class) ==null)
							cyNetwork.getDefaultEdgeTable().getRow(edges.get(0).getSUID()).set(columnName, sm[i][j]);
					}
					
				}
			}
		}
			
}
		
		
//		for(CyEdge edge:edges){
//			
//			String[] usersIds = cyNetwork.getDefaultEdgeTable().getRow(edge.getSUID()).get("shared name", String.class).split(" ");
//			
//			cyNetwork.getDefaultEdgeTable().getRow(edge.getSUID()).set(columnName, 
//			sm[userPositionMapping.getPositionByUserId(usersIds[0])][userPositionMapping.getPositionByUserId(usersIds[2])]);
//		}
		

	/**
	 * @cyNetwork current network
	 * @return list of relationships for current network
	 **/
	public static List<TrustedRelationship> getListTrustedRelationship(CyNetwork cyNetwork){
		
		List<TrustedRelationship> listTr = new Vector<TrustedRelationship>();
		List<CyEdge> edges = cyNetwork.getEdgeList();
		
		for(CyEdge edge:edges){

			String[] usersIds = cyNetwork.getDefaultEdgeTable().getRow(edge.getSUID()).get("shared name", String.class).split(" ");
			
			try{
				Double confianza = cyNetwork.getDefaultEdgeTable().getRow(edge.getSUID()).get("ponderacion", Double.class);
				double num = 0;
				if (confianza != null)
					num = confianza;
				listTr.add(new TrustedRelationship(usersIds[0],usersIds[2],num));
			}
			catch (Exception e){
				e.getMessage();
			}
		}
		
		return listTr;
	}
	

	public static HashMap<String, User> getUserPositinMapping(CyNetwork network){

		List<CyNode> nodes = network.getNodeList();
		HashMap<String, User> usuarios = new HashMap<String, User>();
		for(CyNode node:nodes){
			User usuario = new User();
			usuario.setSuid(node.getSUID());
			usuario.setId(network.getDefaultNodeTable().getRow(node.getSUID()).get("name", String.class));
			usuario.setAthletes(network.getDefaultNodeTable().getRow(node.getSUID()).getList("athletes", String.class));
			usuario.setBooks(network.getDefaultNodeTable().getRow(node.getSUID()).getList("books", String.class ));
			usuario.setGames(network.getDefaultNodeTable().getRow(node.getSUID()).getList("games", String.class));
			usuario.setGender(network.getDefaultNodeTable().getRow(node.getSUID()).get("Gender", String.class));
			usuario.setGroups(network.getDefaultNodeTable().getRow(node.getSUID()).getList("groups", String.class));
			usuario.setLikes(network.getDefaultNodeTable().getRow(node.getSUID()).getList("likes", String.class));
			usuario.setLink(network.getDefaultNodeTable().getRow(node.getSUID()).get("Link", String.class));
			usuario.setMovies(network.getDefaultNodeTable().getRow(node.getSUID()).getList("movies", String.class));
			usuario.setMusic(network.getDefaultNodeTable().getRow(node.getSUID()).getList("music", String.class));
			usuario.setTelevision(network.getDefaultNodeTable().getRow(node.getSUID()).getList("television", String.class));
			usuario.setTeams(network.getDefaultNodeTable().getRow(node.getSUID()).getList("teams", String.class));
			//Busco los amigos
			List<CyNode> amigos = network.getNeighborList(node, Type.ANY);
			List<String> friends = new Vector<String>();
			for (CyNode amigo:amigos){
				friends.add(network.getDefaultNodeTable().getRow(amigo.getSUID()).get("name", String.class));
			}
			usuario.setFriends(friends);
			usuarios.put(usuario.getId(), usuario);
		}
		return usuarios;
	}
	
	public static List<Double> getColumnValueSorted(CyNetwork network, String columnName){
		
		CyColumn column = getCyColumnNetwork(network,columnName);
		List<Double> values = column.getValues(Double.class);
		Collections.sort(values);
		
		return values;
		
	}
	
public static List<Double> getColumnValueSortedEdge(CyNetwork network, String columnName){
		
		CyTable table = network.getDefaultEdgeTable();
		CyColumn column =  table.getColumn(columnName);
		List<Double> values = column.getValues(Double.class);
		Collections.sort(values);
		
		return values;
		
	}
	
	public static Map<Double,Double> getDiscreteMapping(CyNetwork network, String columnName){
		
		Map<Double,Double> map = new HashMap<Double, Double>();
		List<Double> values = getColumnValueSorted(network,columnName);
		
		double max = values.get(values.size()-1);
		
		for (Double val : values) {
			map.put(val,(val*100/max));
		}
		
		return map;
	}
	
	public static void generateHideEdge(CyNetwork network, CyNetworkView cyNetworkView){
		
		if (network.getDefaultEdgeTable().getColumn("Visible") == null)
			network.getDefaultEdgeTable().createColumn("Visible", Boolean.class, false);
		List<CyNode> listNodes = network.getNodeList();
		for(int i = 0;i<listNodes.size();i++){
			for(int j = i;j<listNodes.size();j++){
				if(!listNodes.get(i).equals(listNodes.get(j))){
						if ((!network.containsEdge(listNodes.get(i), listNodes.get(j)))&&(!network.containsEdge(listNodes.get(j), listNodes.get(i)))){
							CyEdge newEdge =network.addEdge(listNodes.get(i), listNodes.get(j), false);
							String nodo1 = network.getDefaultNodeTable().getRow(listNodes.get(i).getSUID()).get("shared name", String.class);
							String nodo2 = network.getDefaultNodeTable().getRow(listNodes.get(j).getSUID()).get("shared name", String.class);
							network.getDefaultEdgeTable().getRow(newEdge.getSUID()).set("shared name",nodo1+" (Amigode) "+nodo2);
							network.getDefaultEdgeTable().getRow(newEdge.getSUID()).set("name",nodo1+" (Amigode) "+nodo2);
							network.getDefaultEdgeTable().getRow(newEdge.getSUID()).set("Visible", false);
						}
					}
			}
		}
	}

}
